﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;

namespace SPMS.Common
{
    /// <summary>
    /// 用于处理以JSON方式返回错误信息的错误捕获特性。
    /// </summary>
    public class JsonHandleErrorAttribute : HandleErrorAttribute
    {
        #region ---Constructor

        /// <summary>
        /// 初始化类型<see cref="JsonHandleErrorAttribute"/>的新实例。
        /// </summary>
        public JsonHandleErrorAttribute()
            : this(JsonErrorResponseMode.Always_OK, HttpStatusCodes.HTTP_OK)
        {
        }

        /// <summary>
        /// 初始化类型<see cref="JsonHandleErrorAttribute"/>的新实例。
        /// </summary>
        /// <param name="mode">反馈模式。</param>
        /// <param name="statusCode">反馈的HTTP状态码。</param>
        public JsonHandleErrorAttribute(JsonErrorResponseMode mode, HttpStatusCodes statusCode = HttpStatusCodes.HTTP_OK)
        {
            //保存参数
            this.m_ResponseMode = mode;
            this.m_StatusCode = statusCode;
        }

        #endregion

        #region ---Public Method

        /// <summary>
        /// 当发生异常时调用。
        /// </summary>
        /// <param name="filterContext">操作-筛选器上下文。</param>
        /// <remarks></remarks>
        public override void OnException(ExceptionContext filterContext)
        {
            //判定是否发生异常
            if (filterContext.Exception != null)
            {
                //用于保存错误提示信息
                string errorMessage = null;

                //用于保存错误码
                int errorCode = 0;

                //判断是否为未登录异常
                if (filterContext.Exception is UnauthenticatedException)
                {
                    errorCode = (int)ErrorCodes.Error_Unauthenticated;
                    errorMessage = SPMS.Common.Properties.Resources.text_error_unauthenticated;
                }
                //判断是否未未授权异常
                else if (filterContext.Exception is UnauthorizedException)
                {
                    errorCode = (int)ErrorCodes.Error_Unauthorized;
                    errorMessage = SPMS.Common.Properties.Resources.text_error_unauthorized;
                }
                //判断是否为业务错误
                else if (filterContext.Exception is BusinessException)
                {
                    errorCode = (int)ErrorCodes.Error_Application;

                    //判断是否开启诊断模式
                    if (this.IsDiagnosticMode)
                    {
                        errorMessage = filterContext.Exception.ToString();
                    }
                    else
                    {
                        errorMessage = filterContext.Exception.Message;
                    }
                }
                //判断是否为未知异常
                else
                {
                    errorCode = (int)ErrorCodes.Error_Unknown;

                    //判断是否开启诊断模式
                    if (this.IsDiagnosticMode)
                    {
                        errorMessage = string.Format("{0}\r\n\r\n{1}", SPMS.Common.Properties.Resources.text_error_unknown, filterContext.Exception.ToString());
                    }
                    else
                    {
                        errorMessage = SPMS.Common.Properties.Resources.text_error_unknown;
                    }
                }

                //处理折行
                errorMessage = errorMessage.Replace("\r\n", "<br/>");

                //判断反馈模式
                if (this.m_ResponseMode == JsonErrorResponseMode.Always_OK)
                {
                    //设置HTTP状态码
                    filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCodes.HTTP_OK;
                }
                else if (this.m_ResponseMode == JsonErrorResponseMode.ErrorCode)
                {
                    //设置HTTP状态码
                    filterContext.HttpContext.Response.StatusCode = errorCode;
                }
                else
                {
                    //设置HTTP状态码
                    filterContext.HttpContext.Response.StatusCode = (int)this.m_StatusCode;
                }

                //创建异常返回结果
                filterContext.Result = new JsonResultEx
                {
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                    Data = new JsonResultViewModel
                    {
                        success = false,
                        code = errorCode,
                        message = errorMessage
                    }
                };

                //设置为当前HTTP请求启用自定义错误。
                filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;

                //设置异常已经被处理
                filterContext.ExceptionHandled = true;
            }
        }

        #endregion

        #region ---Property

        /// <summary>
        /// 获得一个值，该值用于判断当前是否为诊断模式。
        /// </summary>
        /// <returns>
        ///   如果为诊断模式，则为<c>true</c>，否则为<c>false</c>。
        /// </returns>
        public bool IsDiagnosticMode
        {
            get
            {
                //判断是否已经加载
                if (s_IsDiagnosticMode.HasValue)
                {
                    //直接返回
                    return s_IsDiagnosticMode.Value;
                }

                //加载诊断模式设定
                string value = System.Configuration.ConfigurationManager.AppSettings[KEY_DIAGNOSTICMODE];

                //判断是否配置
                if (string.IsNullOrEmpty(value))
                {
                    //设置为没有开启
                    s_IsDiagnosticMode = false;
                }
                else
                {
                    //去掉空格
                    value = value.Trim();

                    //判断是否开启
                    if (string.Compare(value, "true", true) == 0 ||
                        string.Compare(value, "1", true) == 0 ||
                        string.Compare(value, "on", true) == 0)
                    {
                        //设置值
                        s_IsDiagnosticMode = true;
                    }
                    else
                    {
                        //设置为没有开启
                        s_IsDiagnosticMode = false;
                    }
                }

                //返回结果
                return s_IsDiagnosticMode.Value;
            }
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 反馈模式。
        /// </summary>
        private JsonErrorResponseMode m_ResponseMode;

        /// <summary>
        /// HTTP状态码。
        /// </summary>
        private HttpStatusCodes m_StatusCode;

        //用于记录是否为诊断模式
        private static bool? s_IsDiagnosticMode;

        /// <summary>
        /// 诊断模式键值
        /// </summary>
        private const string KEY_DIAGNOSTICMODE = "DiagnosticMode";

        #endregion
    }
}
